package org.sunrise.game.common.network.server;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.Getter;
import lombok.Setter;
import org.sunrise.game.common.log.LogCore;
import org.sunrise.game.common.network.message.MessageType;
import org.sunrise.game.common.network.message.SocketMessage;
import org.sunrise.game.common.utils.Utils;

import java.nio.charset.StandardCharsets;

@Getter
@Setter
public class BaseServerHandler extends SimpleChannelInboundHandler<SocketMessage> {
    private final String nodeId;
    private boolean isAuthMessage = true;// 是否为认证消息
    private String connectNode;

    public BaseServerHandler(String nodeId) {
        this.nodeId = nodeId;
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, SocketMessage socketMessage) throws Exception {
        if (socketMessage.getMessageType() != MessageType.biz) {
            return;
        }
        byte[] data = socketMessage.getData();
        if (isAuthMessage) {
            verify(ctx.channel(), data);
            return;
        }

        // 来自Client的消息
        BaseServerManager.recvFromClient(nodeId, data);
    }

    // 首次收到消息
    private void verify(Channel channel, byte[] data) {
        isAuthMessage = false;
        String message = new String(data, StandardCharsets.UTF_8);
        if (message.startsWith(Utils.CLIENT_CONNECT)) {
            connectNode = message.substring(Utils.CLIENT_CONNECT.length());

            boolean exist = ConnectionManger.isConnectExist(connectNode);
            if (!exist) {
                String sendMsg = Utils.CLIENT_CONNECT_RESPONSE + Utils.SUCCESS + nodeId;
                ConnectionManger.createConnect(connectNode, channel);
                channel.writeAndFlush(new SocketMessage(MessageType.biz, sendMsg.getBytes(StandardCharsets.UTF_8)));

                LogCore.Server.info("recv connection success, connectNode = { {} }, remoteAddress = { {} }", connectNode, channel.remoteAddress());
                onRecvConnect();
            } else {
                String sendMsg = Utils.CLIENT_CONNECT_RESPONSE + Utils.FAILED;
                channel.writeAndFlush(new SocketMessage(MessageType.biz, sendMsg.getBytes(StandardCharsets.UTF_8)));
                channel.close();

                LogCore.Server.info("recv connection failed, connectNode = { {} }, remoteAddress = { {} }", connectNode, channel.remoteAddress());
            }

        } else {
            channel.close();
        }
    }

    public void onRecvConnect() {
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        if (connectNode != null) {
            ConnectionManger.removeConnect(connectNode);
        }
        LogCore.Server.error("disconnected, connectNode = { {} }, remoteAddress = {}", connectNode, ctx.channel().remoteAddress());
        super.channelInactive(ctx);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        LogCore.Server.error("Exception caught, reason = {}, remoteAddress = {}", cause.getMessage(), ctx.channel().remoteAddress());
        ctx.close();
    }
}
